﻿using System;
using System.Collections.Generic;
using NHibernate;
using Neturion.Dados;
using Neturion.IRepositorios;
using NHibernate.Criterion;

namespace Neturion.Repositorios
{
    public class RepositorioPessoa : IRepositorioPessoa
    {
        public Pessoa Inserir(Pessoa pessoa)
        {
            pessoa.DataNascimentoAbertura = pessoa.DataNascimentoAbertura.HasValue
                                                   ? pessoa.DataNascimentoAbertura.GetValueOrDefault().Date
                                                   : pessoa.DataNascimentoAbertura;
            pessoa.FimVigencia = pessoa.FimVigencia.HasValue
                                    ? pessoa.FimVigencia.GetValueOrDefault().Date
                                    : pessoa.FimVigencia;
            pessoa.InicioVigencia = pessoa.InicioVigencia.HasValue
                                        ? pessoa.InicioVigencia.GetValueOrDefault().Date
                                        : pessoa.InicioVigencia;
           
            //definir paternidade das listas
            foreach (Email email in pessoa.ListaEmails)
            {
                email.Pessoa = pessoa;
            }

            foreach (Endereco endereco in pessoa.ListaEnderecos)
            {
                endereco.Pessoa = pessoa;
            }

            foreach (ReferenciaPessoa referenciaPessoa in pessoa.ListaReferenciaPessoas)
            {
                referenciaPessoa.PessoaReferenciada = pessoa;
            }

            foreach (Registro registro in pessoa.ListaRegistros)
            {
                registro.Pessoa = pessoa;
            }

            foreach (Telefone telefone in pessoa.ListaTelefones)
            {
                telefone.Pessoa = pessoa;
            }

            foreach (ContaBanco contaBanco in pessoa.ListaContasBanco)
            {
                contaBanco.Titular = pessoa;
            }

            GerenciadorBDConfigs.Instance.SessaoAtual().Save(pessoa);
            return pessoa;
        }

        public Pessoa Atualizar(Pessoa pessoa)
        {
            Pessoa tmpPessoa = ObterPorId(pessoa.PessoaId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpPessoa.ApelidoFantasia = pessoa.ApelidoFantasia;
            tmpPessoa.CpfCnpj = pessoa.CpfCnpj;
            tmpPessoa.DataCadastro = pessoa.DataCadastro.Date;
            tmpPessoa.DataNascimentoAbertura = pessoa.DataNascimentoAbertura.HasValue
                                                   ? pessoa.DataNascimentoAbertura.GetValueOrDefault().Date
                                                   : pessoa.DataNascimentoAbertura;
            tmpPessoa.EnumEscolaridade = pessoa.EnumEscolaridade;
            tmpPessoa.EnumEstadoCivil = pessoa.EnumEstadoCivil;
            tmpPessoa.EnumTipoPessoa = pessoa.EnumTipoPessoa;
            tmpPessoa.EnumTipoSexo = pessoa.EnumTipoSexo;
            tmpPessoa.FimVigencia = pessoa.FimVigencia.HasValue
                                    ? pessoa.FimVigencia.GetValueOrDefault().Date
                                    : pessoa.FimVigencia;
            tmpPessoa.InicioVigencia = pessoa.InicioVigencia.HasValue
                                        ? pessoa.InicioVigencia.GetValueOrDefault().Date
                                        : pessoa.InicioVigencia;
            tmpPessoa.HomePage = pessoa.HomePage;
            tmpPessoa.NeturionLog = pessoa.NeturionLog;
            tmpPessoa.Midia = pessoa.Midia;
            tmpPessoa.NomeRazaoSocial = pessoa.NomeRazaoSocial;
            tmpPessoa.NomeReduzido = pessoa.NomeReduzido;
            tmpPessoa.Observacao = pessoa.Observacao;
           
            //Listagens
            tmpPessoa.ListaEmails.Clear();
            foreach (Email email in pessoa.ListaEmails)
            {
                tmpPessoa.AdicionarEmail(email);
            }
            
            tmpPessoa.ListaEnderecos.Clear();
            foreach (Endereco endereco in pessoa.ListaEnderecos)
            {
                tmpPessoa.AdicionarEndereco(endereco);
            }

            tmpPessoa.ListaReferenciaPessoas.Clear();
            foreach (ReferenciaPessoa referenciaPessoa in pessoa.ListaReferenciaPessoas)
            {
                tmpPessoa.AdicionarReferenciaPessoa(referenciaPessoa);
            }

            tmpPessoa.ListaRegistros.Clear();
            foreach (Registro registro in pessoa.ListaRegistros)
            {
                tmpPessoa.AdicionarRegistro(registro);
            }

            tmpPessoa.ListaTelefones.Clear();
            foreach (Telefone telefone in pessoa.ListaTelefones)
            {
                tmpPessoa.AdicionarTelefone(telefone);
            }

            tmpPessoa.ListaContasBanco.Clear();
            foreach (ContaBanco contaBanco in pessoa.ListaContasBanco)
            {
                tmpPessoa.AdicionarContaBanco(contaBanco);
            }
            
            GerenciadorBDConfigs.Instance.SessaoAtual().Merge(tmpPessoa);

            return tmpPessoa;
        }

        public void Excluir(Pessoa pessoa)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(pessoa);
        }

        public IList<Pessoa> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Pessoa));
            return criteria.List<Pessoa>() as List<Pessoa>;
        }

        public Pessoa ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<Pessoa>(id);
        }

        public IList<Pessoa> ObterTodos(int inicio, int quantidade, int quantidadeMinima, 
            string nomeRazaoSocial, string apelidoFantasia, 
            string nomeReduzido,  string cpfCnpj, Midia midia, 
            EnumTipoPessoa enumTipoPessoa, DateTime? dataNascimentoAbertura,
            DateTime? inicioVigencia, DateTime? fimVigencia)
        {
            if(quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Pessoa))
                .SetFirstResult(inicio).SetMaxResults(quantidade)
                .Add(Restrictions.Eq("EnumTipoPessoa",enumTipoPessoa));
           
           if (! String.IsNullOrEmpty(nomeRazaoSocial))
           {
               criteria.Add(Restrictions.Like("NomeRazaoSocial", nomeRazaoSocial, MatchMode.Anywhere));
           }

           if (!String.IsNullOrEmpty(apelidoFantasia))
           {
               criteria.Add(Restrictions.Like("ApelidoFantasia", apelidoFantasia, MatchMode.Anywhere));
           }

           if (!String.IsNullOrEmpty(nomeReduzido))
           {
               criteria.Add(Restrictions.Like("NomeReduzido", nomeReduzido, MatchMode.Anywhere));
           }

           if (!String.IsNullOrEmpty(cpfCnpj))
           {
               criteria.Add(Restrictions.Eq("CpfCnpj", cpfCnpj));
           }

           if (midia != null)
           {
               criteria.Add(Restrictions.Eq("Midia", midia));
           }

           if(dataNascimentoAbertura.HasValue)
           {
               criteria.Add(Restrictions.Eq("DataNascimentoAbertura", dataNascimentoAbertura.Value.Date));
           }

           if (inicioVigencia.HasValue)
           {
               criteria.Add(Restrictions.Eq("InicioVigencia", inicioVigencia.Value.Date));
           }

           if (fimVigencia.HasValue)
           {
               criteria.Add(Restrictions.Eq("FimVigencia", fimVigencia.Value.Date));
           }
            
            return criteria.List<Pessoa>() as List<Pessoa>;
        }

        public IList<Pessoa> ObterTodos(int inicio, int quantidade, int quantidadeMinima,
            string nomeRazaoSocial, string apelidoFantasia, 
            string nomeReduzido, string cpfCnpj, 
            Midia midia, EnumTipoPessoa enumTipoPessoa,
            EnumTipoSexo enumTipoSexo, EnumEscolaridade enumEscolaridade, 
            EnumEstadoCivil enumEstadoCivil, DateTime? dataNascimentoAberturaDe, 
            DateTime? dataNascimentoAberturaAte, DateTime? cadastroDe, 
            DateTime? cadastroAte, DateTime? inicioVigenciaDe, 
            DateTime? inicioVigenciaAte, 
            DateTime? fimVigenciaDe, DateTime? fimVigenciaAte)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Pessoa))
                .SetFirstResult(inicio).SetMaxResults(quantidade)
                .Add(Restrictions.Eq("EnumTipoPessoa", enumTipoPessoa));

            if (!String.IsNullOrEmpty(nomeRazaoSocial))
            {
                criteria.Add(Restrictions.Like("NomeRazaoSocial", nomeRazaoSocial, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(apelidoFantasia))
            {
                criteria.Add(Restrictions.Like("ApelidoFantasia", apelidoFantasia, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(nomeReduzido))
            {
                criteria.Add(Restrictions.Like("NomeReduzido", nomeReduzido, MatchMode.Anywhere));
            }

            if (!String.IsNullOrEmpty(cpfCnpj))
            {
                criteria.Add(Restrictions.Eq("CpfCnpj", cpfCnpj));
            }

            if (midia != null)
            {
                criteria.Add(Restrictions.Eq("Midia", midia));
            }

            if (enumTipoSexo > 0)
            {
                criteria.Add(Restrictions.Eq("EnumTipoSexo", enumTipoSexo));
            }

            if (enumEstadoCivil > 0)
            {
                criteria.Add(Restrictions.Eq("EnumEstadoCivil", enumEstadoCivil));
            }

            if (enumEscolaridade > 0)
            {
                criteria.Add(Restrictions.Eq("EnumEscolaridade", enumEscolaridade));
            }

            if (dataNascimentoAberturaDe.HasValue)
            {
                criteria.Add(dataNascimentoAberturaAte.HasValue
                    ? Restrictions.Between("DataNascimentoAbertura", dataNascimentoAberturaDe.Value.Date,dataNascimentoAberturaAte.Value.Date)
                    : Restrictions.Eq("DataNascimentoAbertura", dataNascimentoAberturaDe.Value.Date));
            }

            if (cadastroDe.HasValue)
            {
                criteria.Add(cadastroAte.HasValue
                    ? Restrictions.Between("DataCadastro", cadastroDe.Value.Date, cadastroAte.Value.Date)
                    : Restrictions.Eq("DataCadastro", cadastroDe.Value.Date));
            }

            if (inicioVigenciaDe.HasValue)
            {
                criteria.Add(inicioVigenciaAte.HasValue
                                 ? Restrictions.Between("InicioVigencia", inicioVigenciaDe.Value.Date,inicioVigenciaAte.Value.Date)
                                 : Restrictions.Eq("InicioVigencia", inicioVigenciaDe.Value.Date));
            }

            if (fimVigenciaDe.HasValue)
            {
                criteria.Add(fimVigenciaAte.HasValue
                                 ? Restrictions.Between("FimVigencia", fimVigenciaDe.Value.Date,fimVigenciaAte.Value.Date)
                                 : Restrictions.Eq("FimVigencia", fimVigenciaDe.Value.Date));
            }

            return criteria.List<Pessoa>() as List<Pessoa>;
        }

        public Pessoa ObterPorCpfCnpj(string cpfCnpj)
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Pessoa))
                   .Add(Restrictions.Eq("CpfCnpj", cpfCnpj));
            return criteria.UniqueResult<Pessoa>();
        
        }

        public IList<Pessoa> ObterPorDescricao(string descricao)
        {
            
            ICriteria criteria =
               GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Pessoa))
               .Add(Restrictions.Like("ApelidoFantasia", descricao, MatchMode.Anywhere));
            return criteria.List<Pessoa>() as List<Pessoa>;
        
        }
    }
}
